home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / curses.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  24KB  |  1,061 lines

  1. /* curses.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the functions & variables needed for a tiny subset of
  12.  * curses.  The principle advantage of this version of curses is its
  13.  * extreme speed.  Disadvantages are potentially larger code, few supported
  14.  * functions, limited compatibility with full curses, and only stdscr.
  15.  */
  16.  
  17. #include "config.h"
  18. #include "vi.h"
  19.  
  20. #if ANY_UNIX || OS2
  21. # if UNIXV || COH_386 || OS2
  22. #  ifdef TERMIOS
  23. #   include    <termios.h>
  24. #  else
  25. #   include    <termio.h>
  26. #  endif
  27. #  ifndef OS2
  28. #  ifndef NO_S5WINSIZE
  29. #   ifndef _SEQUENT_
  30. #    include    <sys/stream.h>    /* winsize struct defined in one of these? */
  31. #    include    <sys/ptem.h>
  32. #   endif
  33. #  else
  34. #   undef    TIOCGWINSZ    /* we can't handle it correctly yet */
  35. #  endif
  36. #  endif
  37. # else
  38. #  include    <sgtty.h>
  39. # endif
  40. #endif
  41.  
  42. #if TOS
  43. # include    <osbind.h>
  44. #endif
  45.  
  46. #if OSK
  47. # include    <sgstat.h>
  48. #endif
  49.  
  50. #if VMS
  51. extern int VMS_read_raw;  /* Set in initscr() */
  52. #endif
  53.  
  54.  
  55. static void     starttcap();
  56.  
  57. /* variables, publicly available & used in the macros */
  58. char    *termtype;    /* name of terminal entry */
  59. short    ospeed;        /* speed of the tty, eg B2400 */
  60. #if OSK
  61. char    PC_;    /* Pad char */
  62. char    *BC;    /* backspace character string */
  63. #else
  64. char    PC;        /* Pad char */
  65. #endif
  66. WINDOW    *stdscr;    /* pointer into kbuf[] */
  67. WINDOW    kbuf[KBSIZ];    /* a very large output buffer */
  68. int    LINES;        /* :li#: number of rows */
  69. int    COLS;        /* :co#: number of columns */
  70. int    AM;        /* :am:  boolean: auto margins? */
  71. int    PT;        /* :pt:  boolean: physical tabs? */
  72. char    *VB;        /* :vb=: visible bell */
  73. char    *UP;        /* :up=: move cursor up */
  74. char    *SO = "";    /* :so=: standout start */
  75. char    *SE = "";    /* :se=: standout end */
  76. char    *US = "";    /* :us=: underline start */
  77. char    *UE = "";    /* :ue=: underline end */
  78. char    *MD = "";    /* :md=: bold start */
  79. char    *ME = "";    /* :me=: bold end */
  80. char    *AS = "";    /* :as=: alternate (italic) start */
  81. char    *AE = "";    /* :ae=: alternate (italic) end */
  82. #ifndef NO_VISIBLE
  83. char    *MV;        /* :mv=: "visible" selection start */
  84. #endif
  85. char    *CM;        /* :cm=: cursor movement */
  86. char    *CE;        /* :ce=: clear to end of line */
  87. char    *CD;        /* :cd=: clear to end of screen */
  88. char    *AL;        /* :al=: add a line */
  89. char    *DL;        /* :dl=: delete a line */
  90. #if OSK
  91. char    *SR_;        /* :sr=: scroll reverse */
  92. #else
  93. char    *SR;        /* :sr=: scroll reverse */
  94. #endif
  95. char    *KS = "";    /* :ks=: switch keypad to application mode */
  96. char    *KE = "";    /* :ke=: switch keypad to system mode */
  97. char    *KU;        /* :ku=: key sequence sent by up arrow */
  98. char    *KD;        /* :kd=: key sequence sent by down arrow */
  99. char    *KL;        /* :kl=: key sequence sent by left arrow */
  100. char    *KR;        /* :kr=: key sequence sent by right arrow */
  101. char    *HM;        /* :HM=: key sequence sent by the <Home> key */
  102. char    *EN;        /* :EN=: key sequence sent by the <End> key */
  103. char    *PU;        /* :PU=: key sequence sent by the <PgUp> key */
  104. char    *PD;        /* :PD=: key sequence sent by the <PgDn> key */
  105. char    *KI;        /* :kI=: key sequence sent by the <Insert> key */
  106. #ifndef NO_FKEY
  107. char    *FKEY[NFKEYS];    /* :k0=: ... :k9=: sequences sent by function keys */
  108. #endif
  109. char    *IM = "";    /* :im=: insert mode start */
  110. char    *IC = "";    /* :ic=: insert the following character */
  111. char    *EI = "";    /* :ei=: insert mode end */
  112. char    *DC;        /* :dc=: delete a character */
  113. char    *TI = "";    /* :ti=: terminal init */    /* GB */
  114. char    *TE = "";    /* :te=: terminal exit */    /* GB */
  115. #ifndef NO_CURSORSHAPE
  116. #if 1
  117. char    *CQ = (char *)0;/* :cQ=: normal cursor */
  118. char    *CX = (char *)1;/* :cX=: cursor used for EX command/entry */
  119. char    *CV = (char *)2;/* :cV=: cursor used for VI command mode */
  120. char    *CI = (char *)3;/* :cI=: cursor used for VI input mode */
  121. char    *CR = (char *)4;/* :cR=: cursor used for VI replace mode */
  122. #else
  123. char    *CQ = "";    /* :cQ=: normal cursor */
  124. char    *CX = "";    /* :cX=: cursor used for EX command/entry */
  125. char    *CV = "";    /* :cV=: cursor used for VI command mode */
  126. char    *CI = "";    /* :cI=: cursor used for VI input mode */
  127. char    *CR = "";    /* :cR=: cursor used for VI replace mode */
  128. #endif
  129. #endif
  130. char    *aend = "";    /* end an attribute -- either UE or ME */
  131. char    ERASEKEY;    /* backspace key taken from ioctl structure */
  132. #ifndef NO_COLOR
  133. char    normalcolor[24];
  134. char    SOcolor[24];
  135. char    SEcolor[24];
  136. char    UScolor[24];
  137. char    UEcolor[24];
  138. char    MDcolor[24];
  139. char    MEcolor[24];
  140. char    AScolor[24];
  141. char    AEcolor[24];
  142. # ifndef NO_POPUP
  143. char    POPUPcolor[24];
  144. # endif
  145. # ifndef NO_VISIBLE
  146. char    VISIBLEcolor[24];
  147. # endif
  148. #endif
  149.  
  150. #if ANY_UNIX || OS2
  151. # if UNIXV || COH_386 || OS2
  152. #  ifdef TERMIOS
  153. static struct termios    oldtermio;    /* original tty mode */
  154. static struct termios    newtermio;    /* cbreak/noecho tty mode */
  155. #  else
  156. static struct termio    oldtermio;    /* original tty mode */
  157. static struct termio    newtermio;    /* cbreak/noecho tty mode */
  158. #  endif
  159. # else
  160. static struct sgttyb    oldsgttyb;    /* original tty mode */
  161. static struct sgttyb    newsgttyb;    /* cbreak/nl/noecho tty mode */
  162. static int        oldint;        /* ^C or DEL, the "intr" character */
  163. #  ifdef TIOCSLTC
  164. static int        oldswitch;    /* ^Z, the "suspend" character */
  165. static int        olddswitch;    /* ^Y, the "delayed suspend" char */
  166. static int        oldquote;    /* ^V, the "quote next char" char */
  167. #  endif
  168. # endif
  169. #endif
  170.  
  171. #if OSK
  172. static struct sgbuf    oldsgttyb;    /* orginal tty mode */
  173. static struct sgbuf    newsgttyb;    /* noecho tty mode */
  174. #endif
  175.  
  176. static char    *capbuf;    /* capability string buffer */
  177.  
  178.  
  179. /* Initialize the Curses package. */
  180. void initscr()
  181. {
  182.     /* make sure TERM variable is set */
  183.     termtype = getenv("TERM");
  184.  
  185. #if VMS
  186.     /* VMS getenv() handles TERM as a environment setting.  Foreign 
  187.      * terminal support can be implemented by setting the ELVIS_TERM
  188.      * logical or symbol to match a tinytcap entry.
  189.      */
  190.     if (!strcmp(termtype,"unknown"))
  191.         termtype = getenv("ELVIS_TERM");
  192. #endif
  193. #if MSDOS
  194.     /* For MS-DOS, if TERM is unset we can default to "pcbios", or
  195.      * maybe "rainbow".
  196.      */
  197.     if (!termtype)
  198.     {
  199. #ifdef RAINBOW
  200.         if (*(unsigned char far*)(0xffff000eL) == 6   /* Rainbow 100a */
  201.          || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
  202.         {
  203.             termtype = "rainbow";
  204.         }
  205.         else
  206. #endif
  207.             termtype = "pcbios";
  208.     }
  209.     if (!strcmp(termtype, "pcbios"))
  210. #else
  211.     if (!termtype)
  212. #endif
  213.     {
  214. #if ANY_UNIX
  215.         write(2, "Environment variable TERM must be set\n", (unsigned)38);
  216.         exit(2);
  217. #endif
  218. #if OSK
  219.         writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
  220.         exit(2);
  221. #endif
  222. #if AMIGA
  223.         termtype = TERMTYPE;
  224.         starttcap(termtype);
  225. #endif
  226. #if MSDOS
  227.         starttcap("pcbios");
  228. #endif
  229. #if OS2
  230.         termtype = "ansi";
  231.         starttcap(termtype);
  232. #endif
  233. #if TOS
  234.         termtype = "vt52";
  235.         starttcap(termtype);
  236. #endif
  237. #if VMS
  238.         write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
  239.         exit(2);
  240. #endif
  241.     }
  242.     else
  243.     {
  244. #if MSDOS
  245.         *o_pcbios = 0;
  246. #endif
  247.         /* start termcap stuff */
  248.         starttcap(termtype);
  249.     }
  250.  
  251.     /* create stdscr and curscr */
  252.     stdscr = kbuf;
  253.  
  254.     /* change the terminal mode to cbreak/noecho */
  255. #if ANY_UNIX || OS2
  256. # if UNIXV || COH_386 || OS2
  257. #  ifdef TERMIOS
  258.     tcgetattr(2, &oldtermio);
  259. #  else
  260.     ioctl(2, TCGETA, &oldtermio);
  261. #  endif
  262. # else
  263.     ioctl(2, TIOCGETP, &oldsgttyb);
  264. # endif
  265. #endif
  266.  
  267. #if OSK
  268.     _gs_opt(0, &oldsgttyb);
  269. #endif
  270.  
  271. #if VMS
  272.     VMS_read_raw = 1;   /* cbreak/noecho */
  273.     vms_open_tty();
  274. #endif
  275.     resume_curses(TRUE);
  276. }
  277.  
  278. /* Shut down the Curses package. */
  279. void endwin()
  280. {
  281.     /* change the terminal mode back the way it was */
  282.     suspend_curses();
  283. #if AMIGA
  284.     amiclosewin();
  285. #endif
  286. }
  287.  
  288.  
  289. static int curses_active = FALSE;
  290.  
  291. extern int oldcurs;
  292.  
  293. /* Send any required termination strings.  Turn off "raw" mode. */
  294. void suspend_curses()
  295. {
  296. #if ANY_UNIX && !(UNIXV || COH_386)
  297.     struct tchars    tbuf;
  298. # ifdef TIOCSLTC
  299.     struct ltchars    ltbuf;
  300. # endif
  301. #endif
  302. #ifndef NO_CURSORSHAPE
  303.     if (has_CQ)
  304.     {
  305.         do_CQ();
  306.         oldcurs = 0;
  307.     }
  308. #endif
  309.     if (has_TE)                    /* GB */
  310.     {
  311.         do_TE();
  312.     }
  313.     if (has_KE)
  314.     {
  315.         do_KE();
  316.     }
  317. #ifndef NO_COLOR
  318.     quitcolor();
  319. #endif
  320.     refresh();
  321.  
  322.     /* change the terminal mode back the way it was */
  323. #if ANY_UNIX || OS2
  324. # if (UNIXV || COH_386 || OS2)
  325. #  ifdef TERMIOS
  326.     tcsetattr(2, TCSADRAIN, &oldtermio);
  327. #  else
  328.     ioctl(2, TCSETAW, &oldtermio);
  329. #  endif
  330. # else
  331.     ioctl(2, TIOCSETP, &oldsgttyb);
  332.  
  333.     ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf);
  334.     tbuf.t_intrc = oldint;
  335.     ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf);
  336.  
  337. #  ifdef TIOCSLTC
  338.     ioctl(2, TIOCGLTC, <buf);
  339.     ltbuf.t_suspc = oldswitch;
  340.     ltbuf.t_dsuspc = olddswitch;
  341.     ltbuf.t_lnextc = oldquote;
  342.     ioctl(2, TIOCSLTC, <buf);
  343. #  endif
  344. # endif
  345. #endif
  346. #if OSK
  347.     _ss_opt(0, &oldsgttyb);
  348. #endif
  349. #if AMIGA
  350.     ttyshutdown();
  351. #endif
  352. #if MSDOS || OS2
  353.     raw_set_stdio(FALSE);
  354. #endif
  355.  
  356. #if VMS
  357.     VMS_read_raw = 0;
  358. #endif
  359.     curses_active = FALSE;
  360. }
  361.  
  362.  
  363. /* put the terminal in RAW mode.  If "quietly" is FALSE, then ask the user
  364.  * to hit a key, and wait for keystroke before returning.
  365.  */
  366. void resume_curses(quietly)
  367.     int    quietly;
  368. {
  369.     if (!curses_active)
  370.     {
  371.         /* change the terminal mode to cbreak/noecho */
  372. #if ANY_UNIX || OS2
  373. # if UNIXV || COH_386 || OS2
  374.         ospeed = (oldtermio.c_cflag & CBAUD);
  375.         ERASEKEY = oldtermio.c_cc[VERASE];
  376.         newtermio = oldtermio;
  377.         newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
  378.         newtermio.c_oflag &= ~OPOST;
  379.         newtermio.c_lflag &= ISIG;
  380.         newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
  381.         newtermio.c_cc[VMIN] = 1;
  382.         newtermio.c_cc[VTIME] = 0;
  383. #  ifdef VSWTCH
  384.         newtermio.c_cc[VSWTCH] = 0;
  385. #  endif
  386. #  ifdef VSUSP
  387.         newtermio.c_cc[VSUSP] = 0;
  388. #  endif
  389. #  ifdef TERMIOS
  390.         tcsetattr(2, TCSADRAIN, &newtermio);
  391. #  else
  392.         ioctl(2, TCSETAW, &newtermio);
  393. #  endif
  394. # else /* BSD, V7, Coherent-286, or Minix */
  395.         struct tchars    tbuf;
  396. #  ifdef TIOCSLTC
  397.         struct ltchars    ltbuf;
  398. #  endif
  399.  
  400.         ospeed = oldsgttyb.sg_ospeed;
  401.         ERASEKEY = oldsgttyb.sg_erase;
  402.         newsgttyb = oldsgttyb;
  403.         newsgttyb.sg_flags |= CBREAK;
  404.         newsgttyb.sg_flags &= ~(CRMOD|ECHO|XTABS);
  405.         ioctl(2, TIOCSETP, &newsgttyb);
  406.  
  407.         ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf);
  408.         oldint = tbuf.t_intrc;
  409.         tbuf.t_intrc = ctrl('C');    /* always use ^C for interrupts */
  410.         ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf);
  411.  
  412. #  ifdef TIOCSLTC
  413.         ioctl(2, TIOCGLTC, <buf);
  414.         oldswitch = ltbuf.t_suspc;
  415.         ltbuf.t_suspc = 0;        /* disable ^Z for elvis */
  416.         olddswitch = ltbuf.t_dsuspc;
  417.         ltbuf.t_dsuspc = 0;        /* disable ^Y for elvis */
  418.         oldquote = ltbuf.t_lnextc;
  419.         ltbuf.t_lnextc = 0;        /* disable ^V for elvis */
  420.         ioctl(2, TIOCSLTC, <buf);
  421. #  endif
  422.  
  423. # endif
  424. #endif
  425. #if OSK
  426.         newsgttyb = oldsgttyb;
  427.         newsgttyb.sg_echo = 0;
  428.         newsgttyb.sg_eofch = 0;
  429.         newsgttyb.sg_kbach = 0;
  430.         newsgttyb.sg_kbich = ctrl('C');
  431.         _ss_opt(0, &newsgttyb);
  432.         ospeed = oldsgttyb.sg_baud;
  433.         ERASEKEY = oldsgttyb.sg_bspch;
  434. #endif
  435. #if AMIGA
  436.         /* turn on window resize and RAW */
  437.         ttysetup();
  438. #endif
  439. #if MSDOS || OS2
  440.         raw_set_stdio(TRUE);
  441. #endif
  442.  
  443. #if VMS
  444.         VMS_read_raw = 1;
  445.         { int c;
  446.             read(0,&c,0);   /* Flush the tty buffer. */
  447.         }
  448.         ERASEKEY = '\177';  /* Accept <DEL> as <^H> for VMS */
  449. #endif
  450.  
  451.         curses_active = TRUE;
  452.     }
  453.  
  454.     /* If we're supposed to quit quietly, then we're done */
  455.     if (quietly)
  456.     {
  457.         if (has_TI)                    /* GB */
  458.         {
  459.             do_TI();
  460.         }
  461.         if (has_KS)
  462.         {
  463.             do_KS();
  464.         }
  465.  
  466.         return;
  467.     }
  468.  
  469.     signal(SIGINT, SIG_IGN);
  470.  
  471.     move(LINES - 1, 0);
  472.     do_SO();
  473. #if VMS
  474.     qaddstr("\n[Press <RETURN> to continue]");
  475. #else
  476.     qaddstr("[Press <RETURN> to continue]");
  477. #endif
  478.     do_SE();
  479.     refresh();
  480.     ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
  481.     if (has_TI)
  482.     {
  483.         do_TI();
  484.     }
  485.     if (kbuf[0] == ':')
  486.     {
  487.         mode = MODE_COLON;
  488.         addch('\n');
  489.         refresh();
  490.     }
  491.     else
  492.     {
  493.         mode = MODE_VI;
  494.         redraw(MARK_UNSET, FALSE);
  495.     }    
  496.     exwrote = FALSE;
  497.  
  498.     signal(SIGINT, trapint);
  499. }
  500.  
  501. /* This function fetches an optional string from termcap */
  502. static void mayhave(T, s)
  503.     char    **T;    /* where to store the returned pointer */
  504.     char    *s;    /* name of the capability */
  505. {
  506.     char    *val;
  507.  
  508.     val = tgetstr(s, &capbuf);
  509.     if (val)
  510.     {
  511.         *T = val;
  512.     }
  513. }
  514.  
  515.  
  516. /* This function fetches a required string from termcap */
  517. static void musthave(T, s)
  518.     char    **T;    /* where to store the returned pointer */
  519.     char    *s;    /* name of the capability */
  520. {
  521.     mayhave(T, s);
  522.     if (!*T)
  523.     {
  524.         write(2, "This termcap entry lacks the :", (unsigned)30);
  525.         write(2, s, (unsigned)2);
  526.         write(2, "=: capability\n", (unsigned)14);
  527. #if OSK
  528.         write(2, "\l", 1);
  529. #endif
  530.         exit(2);
  531.     }
  532. }
  533.  
  534.  
  535. /* This function fetches a pair of strings from termcap.  If one of them is
  536.  * missing, then the other one is ignored.
  537.  */
  538. static void pair(T, U, sT, sU)
  539.     char    **T;    /* where to store the first pointer */
  540.     char    **U;    /* where to store the second pointer */
  541.     char    *sT;    /* name of the first capability */
  542.     char    *sU;    /* name of the second capability */
  543. {
  544.     mayhave(T, sT);
  545.     mayhave(U, sU);
  546.     if (!**T || !**U)
  547.     {
  548.         *T = *U = "";
  549.     }
  550. }
  551.  
  552.  
  553.  
  554. /* Read everything from termcap */
  555. static void starttcap(term)
  556.     char    *term;
  557. {
  558.     static char    cbmem[800];
  559.  
  560.     /* allocate memory for capbuf */
  561.     capbuf = cbmem;
  562.  
  563.     /* get the termcap entry */
  564.     switch (tgetent(kbuf, term))
  565.     {
  566.       case -1:
  567.         write(2, "Can't read /etc/termcap\n", (unsigned)24);
  568. #if OSK
  569.         write(2, "\l", 1);
  570. #endif
  571.         exit(2);
  572.  
  573.       case 0:
  574.         write(2, "Unrecognized TERM type\n", (unsigned)23);
  575. #if OSK
  576.         write(2, "\l", 1);
  577. #endif
  578.         exit(3);
  579.     }
  580.  
  581.     /* get strings */
  582.     musthave(&UP, "up");
  583.     mayhave(&VB, "vb");
  584.     musthave(&CM, "cm");
  585.     pair(&SO, &SE, "so", "se");
  586.     mayhave(&TI, "ti");
  587.     mayhave(&TE, "te");
  588.     if (tgetnum("ug") <= 0)
  589.     {
  590.         pair(&US, &UE, "us", "ue");
  591.         pair(&MD, &ME, "md", "me");
  592.  
  593.         /* get italics, or have it default to underline */
  594.         pair(&AS, &AE, "as", "ae");
  595.         if (!*AS)
  596.         {
  597.             AS = US;
  598.             AE = UE;
  599.         }
  600.     }
  601. #ifndef NO_VISIBLE
  602.     MV = SO; /* by default */
  603.     mayhave(&MV, "mv");
  604. #endif
  605.     mayhave(&AL, "al");
  606.     mayhave(&DL, "dl");
  607.     musthave(&CE, "ce");
  608.     mayhave(&CD, "cd");
  609. #if OSK
  610.     mayhave(&SR_, "sr");
  611. #else    
  612.     mayhave(&SR, "sr");
  613. #endif
  614.     pair(&IM, &EI, "im", "ei");
  615.     mayhave(&IC, "ic");
  616.     mayhave(&DC, "dc");
  617.  
  618.     /* other termcap stuff */
  619.     AM = (tgetflag("am") && !tgetflag("xn"));
  620.     PT = tgetflag("pt");
  621. #if AMIGA
  622.     amiopenwin(termtype);    /* Must run this before ttysetup(); */
  623.     ttysetup();    /* Must run this before getsize(0); */
  624. #endif
  625.     getsize(0);
  626.  
  627.     /* Key sequences */
  628.     pair(&KS, &KE, "ks", "ke");    /* keypad enable/disable */
  629.     mayhave(&KU, "ku");        /* up */
  630.     mayhave(&KD, "kd");        /* down */
  631.     mayhave(&KR, "kr");        /* right */
  632.     mayhave(&KL, "kl");        /* left */
  633.     if (KL && KL[0]=='\b' && !KL[1])
  634.     {
  635.         /* never use '\b' as a left arrow! */
  636.         KL = (char *)0;
  637.     }
  638.     mayhave(&PU, "kP");        /* PgUp */
  639.     mayhave(&PD, "kN");        /* PgDn */
  640.     mayhave(&HM, "kh");        /* Home */
  641.     mayhave(&EN, "kH");        /* End */
  642.     mayhave(&KI, "kI");        /* Insert */
  643. #ifndef CRUNCH
  644.     if (!PU) mayhave(&PU, "K2");    /* "3x3 pad" names for PgUp, etc. */
  645.     if (!PD) mayhave(&PD, "K5");
  646.     if (!HM) mayhave(&HM, "K1");
  647.     if (!EN) mayhave(&EN, "K4");
  648.  
  649.     mayhave(&PU, "PU");        /* old XENIX names for PgUp, etc. */
  650.     mayhave(&PD, "PD");        /* (overrides others, if used.) */
  651.     mayhave(&HM, "HM");
  652.     mayhave(&EN, "EN");
  653. #endif
  654. #ifndef NO_FKEY
  655.     mayhave(&FKEY[0], "k0");        /* function key codes */
  656.     mayhave(&FKEY[1], "k1");
  657.     mayhave(&FKEY[2], "k2");
  658.     mayhave(&FKEY[3], "k3");
  659.     mayhave(&FKEY[4], "k4");
  660.     mayhave(&FKEY[5], "k5");
  661.     mayhave(&FKEY[6], "k6");
  662.     mayhave(&FKEY[7], "k7");
  663.     mayhave(&FKEY[8], "k8");
  664.     mayhave(&FKEY[9], "k9");
  665. # ifndef NO_SHIFT_FKEY
  666.     mayhave(&FKEY[10], "s0");        /* shift function key codes */
  667.     mayhave(&FKEY[11], "s1");
  668.     mayhave(&FKEY[12], "s2");
  669.     mayhave(&FKEY[13], "s3");
  670.     mayhave(&FKEY[14], "s4");
  671.     mayhave(&FKEY[15], "s5");
  672.     mayhave(&FKEY[16], "s6");
  673.     mayhave(&FKEY[17], "s7");
  674.     mayhave(&FKEY[18], "s8");
  675.     mayhave(&FKEY[19], "s9");
  676. #  ifndef NO_CTRL_FKEY
  677.     mayhave(&FKEY[20], "c0");        /* control function key codes */
  678.     mayhave(&FKEY[21], "c1");
  679.     mayhave(&FKEY[22], "c2");
  680.     mayhave(&FKEY[23], "c3");
  681.     mayhave(&FKEY[24], "c4");
  682.     mayhave(&FKEY[25], "c5");
  683.     mayhave(&FKEY[26], "c6");
  684.     mayhave(&FKEY[27], "c7");
  685.     mayhave(&FKEY[28], "c8");
  686.     mayhave(&FKEY[29], "c9");
  687. #   ifndef NO_ALT_FKEY
  688.     mayhave(&FKEY[30], "a0");        /* alt function key codes */
  689.     mayhave(&FKEY[31], "a1");
  690.     mayhave(&FKEY[32], "a2");
  691.     mayhave(&FKEY[33], "a3");
  692.     mayhave(&FKEY[34], "a4");
  693.     mayhave(&FKEY[35], "a5");
  694.     mayhave(&FKEY[36], "a6");
  695.     mayhave(&FKEY[37], "a7");
  696.     mayhave(&FKEY[38], "a8");
  697.     mayhave(&FKEY[39], "a9");
  698. #   endif
  699. #  endif
  700. # endif
  701. #endif
  702.  
  703. #ifndef NO_CURSORSHAPE
  704.     /* cursor shapes */
  705.     CQ = tgetstr("cQ", &capbuf);
  706.     if (has_CQ)
  707.     {
  708.         CX = tgetstr("cX", &capbuf);
  709.         if (!CX) CX = CQ;
  710.         CV = tgetstr("cV", &capbuf);
  711.         if (!CV) CV = CQ;
  712.         CI = tgetstr("cI", &capbuf);
  713.         if (!CI) CI = CQ;
  714.         CR = tgetstr("cR", &capbuf);
  715.         if (!CR) CR = CQ;
  716.     }
  717. # ifndef CRUNCH
  718.     else
  719.     {
  720.         CQ = CV = "";
  721.         pair(&CQ, &CV, "ve", "vs");
  722.         CX = CI = CR = CQ;
  723.     }
  724. # endif /* !CRUNCH */
  725. #endif /* !NO_CURSORSHAPE */
  726.  
  727. #ifndef NO_COLOR
  728.     strcpy(SOcolor, SO);
  729.     strcpy(SEcolor, SE);
  730.     strcpy(AScolor, AS);
  731.     strcpy(AEcolor, AE);
  732.     strcpy(MDcolor, MD);
  733.     strcpy(MEcolor, ME);
  734.     strcpy(UScolor, US);
  735.     strcpy(UEcolor, UE);
  736. # ifndef NO_POPUP
  737.     strcpy(POPUPcolor, SO);
  738. # endif
  739. # ifndef NO_VISIBLE
  740.     strcpy(VISIBLEcolor, MV);
  741. # endif
  742. #endif
  743.  
  744. }
  745.  
  746.  
  747. /* This function gets the window size.  It uses the TIOCGWINSZ ioctl call if
  748.  * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
  749.  * This function is called once during initialization, and thereafter it is
  750.  * called whenever the SIGWINCH signal is sent to this process.
  751.  */
  752. int getsize(signo)
  753.     int    signo;
  754. {
  755.     int    lines;
  756.     int    cols;
  757. #ifdef TIOCGWINSZ
  758.     struct winsize size;
  759. #endif
  760.  
  761. #ifdef SIGWINCH
  762.     /* reset the signal vector */
  763.     signal(SIGWINCH, getsize);
  764. #endif
  765.  
  766.     /* get the window size, one way or another. */
  767.     lines = cols = 0;
  768. #ifdef TIOCGWINSZ
  769.     if (ioctl(2, TIOCGWINSZ, &size) >= 0)
  770.     {
  771.         lines = size.ws_row;
  772.         cols = size.ws_col;
  773.     }
  774. #endif
  775. #if AMIGA
  776.     /* Amiga gets window size by asking the console.device */
  777.     if (!strcmp(TERMTYPE, termtype))
  778.     {
  779.         auto long len;
  780.         auto char buf[30];
  781.         
  782.         Write(Output(), "\2330 q", 4); /* Ask the console.device */
  783.         len = Read(Input(), buf, 29);
  784.         buf[len] = '\000';
  785.         sscanf(&buf[5], "%d;%d", &lines, &cols);
  786.     }
  787. #endif
  788. #if OS2
  789.         {
  790.         int buf[2];
  791.         _scrsize(buf);
  792.         lines = buf[1];
  793.         cols = buf[0];
  794.     }
  795. #endif
  796.     if ((lines == 0 || cols == 0) && signo == 0)
  797.     {
  798.         LINES = tgetnum("li");
  799.         COLS = tgetnum("co");
  800.     }
  801. #if MSDOS
  802. # ifdef RAINBOW
  803.     if (!strcmp(termtype, "rainbow"))
  804.     {
  805.         /* Determine whether Rainbow is in 80-column or 132-column mode */
  806.         cols = *(unsigned char far *)0xee000f57L;
  807.     }
  808.     else
  809. # endif
  810.     {
  811.         lines = v_rows();
  812.         cols = v_cols();
  813.     }
  814. #endif
  815.     if (lines >= 2 && cols >= 30)
  816.     {
  817.         LINES = lines;
  818.         COLS = cols;
  819.     }
  820.  
  821.     /* Make sure we got values that we can live with */
  822.     if (LINES < 2 || COLS < 30)
  823.     {
  824.         write(2, "Screen too small\n", (unsigned)17);
  825. #if OSK
  826.         write(2, "\l", 1);
  827. #endif
  828.         endwin();
  829.         exit(2);
  830.     }
  831.  
  832. #if AMIGA
  833.     if (*o_lines != LINES || *o_columns != COLS)
  834.     {
  835.         *o_lines = LINES;
  836.         *o_columns = COLS;
  837.     }
  838. #endif
  839.  
  840.     return 0;
  841. }
  842.  
  843.  
  844. /* This is a function version of addch() -- it is used by tputs() */
  845. int faddch(ch)
  846.     int    ch;
  847. {
  848.     addch(ch);
  849.  
  850.     return 0;
  851. }
  852.  
  853. /* This function quickly adds a string to the output queue.  It does *NOT*
  854.  * convert \n into <CR><LF>.
  855.  */
  856. void qaddstr(str)
  857.     char    *str;
  858. {
  859.     REG char *s_, *d_;
  860.  
  861. #if MSDOS
  862.     if (o_pcbios[0])
  863.     {
  864.         while (*str)
  865.             qaddch(*str++);
  866.         return;
  867.     }
  868. #endif
  869.     for (s_=(str), d_=stdscr; *d_++ = *s_++; )
  870.     {
  871.     }
  872.     stdscr = d_ - 1;
  873. }
  874.  
  875. /* Output the ESC sequence needed to go into any video mode, if supported */
  876. void attrset(a)
  877.     int    a;
  878. {
  879.     do_aend();
  880.     if (a == A_BOLD)
  881.     {
  882.         do_MD();
  883.         aend = ME;
  884.     }
  885.     else if (a == A_UNDERLINE)
  886.     {
  887.         do_US();
  888.         aend = UE;
  889.     }
  890.     else if (a == A_ALTCHARSET)
  891.     {
  892.         do_AS();
  893.         aend = AE;
  894.     }
  895.     else
  896.     {
  897.         aend = "";
  898.     }
  899. }
  900.  
  901.  
  902. /* Insert a single character into the display */
  903. void insch(ch)
  904.     int    ch;
  905. {
  906.     if (has_IM)
  907.         do_IM();
  908.     do_IC();
  909.     qaddch(ch);
  910.     if (has_EI)
  911.         do_EI();
  912. }
  913.  
  914. void wrefresh()
  915. {
  916.     if (stdscr != kbuf)
  917.     {
  918.         VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
  919.         stdscr = kbuf;
  920.     }
  921. }
  922.  
  923. void wqrefresh()
  924. {
  925.     if (stdscr - kbuf > 2000)
  926.     {
  927.         VOIDBIOS(stdscr = kbuf,
  928.         {
  929.             ttywrite(kbuf, (unsigned)(stdscr - kbuf)); 
  930.             stdscr = kbuf;
  931.         });
  932.     }
  933. }
  934.  
  935. #ifndef NO_COLOR
  936. /* This function is called during termination.  It resets color modes */
  937. int ansiquit()
  938. {
  939.     /* if ANSI terminal & colors were set, then reset the colors */
  940.     if (!strcmp(UP, "\033[A") &&  strcmp(SOcolor, SO))
  941.     {
  942.         tputs("\033[37;40m\033[m", 1, faddch);
  943.         clrtoeol();
  944.         return 1;
  945.     }
  946.     return 0;
  947. }
  948.  
  949. /* This sets the color strings that work for ANSI terminals.  If the TERMCAP
  950.  * doesn't look like an ANSI terminal, then it returns FALSE.  If the colors
  951.  * aren't understood, it also returns FALSE.  If all goes well, it returns TRUE
  952.  */
  953. int ansicolor(cmode, attrbyte)
  954.     int    cmode;        /* mode to set, e.g. A_NORMAL */
  955.     int    attrbyte;    /* IBM PC attribute byte */
  956. {
  957.     char    temp[24];    /* hold the new mode string */
  958.  
  959.     /* if not ANSI-ish, then fail */
  960.     if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
  961.     {
  962.         /* Only give an error message if we're editing a file.
  963.          * (I.e., if we're *NOT* currently doing a ".exrc")
  964.          */
  965.         if (tmpfd >= 0)
  966.             msg("Don't know how to set colors for this terminal");
  967.         return FALSE;
  968.     }
  969.  
  970.     /* construct the color string */
  971. #ifdef MWC /* either Coherent-286 ("COHERENT"), or Coherent-386 ("M_SYSV") */
  972.     sprintf(temp, "\033[m\033[3%cm\033[4%cm%s%s",
  973.         "04261537"[attrbyte & 0x07],
  974.         "04261537"[(attrbyte >> 4) & 0x07],
  975.         (attrbyte & 0x08) ? "\033[1m" : "",
  976.         (attrbyte & 0x80) ? "\033[5m" : "");
  977. #else
  978.     sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
  979.         "04261537"[attrbyte & 0x07],
  980.         "04261537"[(attrbyte >> 4) & 0x07],
  981.         (attrbyte & 0x08) ? ";1" : "",
  982.         (attrbyte & 0x80) ? ";5" : "");
  983. #endif
  984.  
  985.     /* stick it in the right place */
  986.     switch (cmode)
  987.     {
  988.       case A_NORMAL:
  989.         if (!strcmp(MEcolor, normalcolor))
  990.             strcpy(MEcolor, temp);
  991.         if (!strcmp(UEcolor, normalcolor))
  992.             strcpy(UEcolor, temp);
  993.         if (!strcmp(AEcolor, normalcolor))
  994.             strcpy(AEcolor, temp);
  995.         if (!strcmp(SEcolor, normalcolor))
  996.             strcpy(SEcolor, temp);
  997.  
  998.         strcpy(normalcolor, temp);
  999.         tputs(normalcolor, 1, faddch);
  1000.         break;
  1001.  
  1002.       case A_BOLD:
  1003.         strcpy(MDcolor, temp);
  1004.         strcpy(MEcolor, normalcolor);
  1005.         break;
  1006.  
  1007.       case A_UNDERLINE:
  1008.         strcpy(UScolor, temp);
  1009.         strcpy(UEcolor, normalcolor);
  1010.         break;
  1011.  
  1012.       case A_ALTCHARSET:
  1013.         strcpy(AScolor, temp);
  1014.         strcpy(AEcolor, normalcolor);
  1015.         break;
  1016.  
  1017.       case A_STANDOUT:
  1018.         strcpy(SOcolor, temp);
  1019.         strcpy(SEcolor, normalcolor);
  1020.         break;
  1021.  
  1022. #ifndef NO_POPUP
  1023.       case A_POPUP:
  1024.         strcpy(POPUPcolor, temp);
  1025.         break;
  1026. #endif
  1027.  
  1028. #ifndef NO_VISIBLE
  1029.       case A_VISIBLE:
  1030.         strcpy(VISIBLEcolor, temp);
  1031.         break;
  1032. #endif
  1033.     }
  1034.  
  1035.     return TRUE;
  1036. }
  1037.  
  1038.  
  1039. /* This function outputs the ESC sequence needed to switch the screen back
  1040.  * to "normal" mode.  On color terminals which haven't had their color set
  1041.  * yet, this is one of the termcap strings; for color terminals that really
  1042.  * have had colors defined, we just the "normal color" escape sequence.
  1043.  */
  1044. int
  1045. endcolor()
  1046. {
  1047.     if (aend == ME)
  1048.         tputs(MEcolor, 1, faddch);
  1049.     else if (aend == UE)
  1050.         tputs(UEcolor, 1, faddch);
  1051.     else if (aend == AE)
  1052.         tputs(AEcolor, 1, faddch);
  1053.     else if (aend == SE)
  1054.         tputs(SEcolor, 1, faddch);
  1055.     aend = "";
  1056.     return 0;
  1057. }
  1058.  
  1059.  
  1060. #endif /* !NO_COLOR */
  1061.